package com.ruoyi.web.util.pdf;

import com.itextpdf.awt.geom.Rectangle2D;
import com.itextpdf.text.pdf.PdfReader;
import com.itextpdf.text.pdf.SimpleBookmark;
import com.itextpdf.text.pdf.parser.ImageRenderInfo;
import com.itextpdf.text.pdf.parser.PdfReaderContentParser;
import com.itextpdf.text.pdf.parser.RenderListener;
import com.itextpdf.text.pdf.parser.TextRenderInfo;

import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;

import static com.ruoyi.common.utils.file.FileUtils.File2byte;


/**
 *  PDF定位方式工具类
 */
public class PDFLocationUtils {


    public static void main(String[] args) throws IOException {
//        System.out.println(locationByBookMark(File2byte("D:\\Desktop\\GoodsReg.pdf"),"SIGNATRUE1"));
//        System.out.println(locationByBookMark(File2byte("D:\\Desktop\\GoodsReg.pdf"),"PO_Img_bar"));
//        System.out.println(locationByBookMark(File2byte("D:\\Desktop\\GoodsReg.pdf"),"PO_T001"));
//        System.out.println(locationByBookMark(File2byte("D:\\Desktop\\GoodsReg.pdf"),"SIGNATRUE1"));

//        System.out.println(getLastKeyWordXX(File2byte("D:\\Desktop\\20220519100541(1).pdf"),1));
        float cd =  841.92f;
        float a = (210*cd)/595.32f;
        System.out.println(a);
    }

    public static List<Location> getLastKeyWord1(byte[] pdfByte, String signKeyWord)
    {
        PdfReader reader = null;
        try{
            // 读取pdf内容
            reader = new PdfReader(pdfByte);
            int pageNum = reader.getNumberOfPages();
            // 签章位置对象
            List<Location> locationList = new LinkedList<>();
            // 下标从1开始
            for (int page = 1; page <= pageNum; page++) {
                Location locationBase = new Location();
                locationBase.setPageNum(page);
                PdfReaderContentParser pdfReaderContentParser = new PdfReaderContentParser(reader);
                pdfReaderContentParser.processContent(page, new RenderListener() {
                    StringBuilder sb = new StringBuilder("");
                    int maxLength = signKeyWord.length();
                    @Override
                    public void renderText(TextRenderInfo textRenderInfo){
                        // 只适用 单字块文档 以及 关键字整个为一个块的情况
                        // 设置 关键字文本为单独的块，不然会错位
                        String aa = textRenderInfo.getText().replace(" ", "").toLowerCase();
                        boolean isKeywordChunk = aa.length() == maxLength;
                        if (isKeywordChunk) {
                            // 文档按照 块 读取
                            sb.delete(0, sb.length());
                            sb.append(aa);
                        } else {
                            // 有些文档 单字一个块的情况
                            // 拼接字符串
                            sb.append(aa);
                            // 去除首部字符串，使长度等于关键字长度
                            if (sb.length() > maxLength) {
                                sb.delete(0, sb.length() - maxLength);
                            }
                        }
                        // 判断是否匹配上
                        if (signKeyWord.equals(sb.toString())) {
                            Location location = locationBase.copy();
                            com.itextpdf.awt.geom.Rectangle2D.Float baseFloat = textRenderInfo.getBaseline()
                                    .getBoundingRectange();
                            com.itextpdf.awt.geom.Rectangle2D.Float ascentFloat = textRenderInfo.getAscentLine()
                                    .getBoundingRectange();
                            float centreX;
                            float centreY;
                            // 计算左上点坐标
                            if (isKeywordChunk) {
                                centreX = baseFloat.x ;
                                centreY = baseFloat.y + ((ascentFloat.y - baseFloat.y));
                            } else {
                                centreX = baseFloat.x;
                                centreY = baseFloat.y + ((ascentFloat.y - baseFloat.y) );
                            }

                            location.setX(centreX);
                            location.setY(centreY);
                            double width = baseFloat.getWidth();
                            double height = baseFloat.getHeight();
                            location.setWidth(width);
                            location.setHeight(height);
                            location.setText(sb.toString());
                            locationList.add(location);
                            // 匹配完后 清除
                            sb.delete(0, sb.length());
                        }
                    }
                    @Override
                    public void renderImage(ImageRenderInfo arg0) {
                        // nothing
                    }

                    @Override
                    public void endTextBlock() {
                        // nothing
                    }

                    @Override
                    public void beginTextBlock() {
                        // nothing
                    }
                });
            }
            if (locationList.isEmpty()) {
                return null;
            }
            return locationList;
        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            if (reader != null) {
                reader.close();
            }
        }
        return null;
    }

    /**
     *  根据获得的 pdfreader 和页码数字解析文本获得Location 对象即位置信息
     * @param pdfReader
     * @param pageNum
     * @return
     * @throws IOException
     */
    //获得某一页的关键字信息的集合
    public static List<Location> getKeyWords(PdfReader pdfReader, final int pageNum) throws IOException {
        List<Location> locations = new ArrayList<Location>();
        try {
            PdfReaderContentParser pdfReaderContentParser = new PdfReaderContentParser(
                    pdfReader);
            pdfReaderContentParser.processContent(pageNum, new RenderListener() {
                @Override
                public void beginTextBlock() {
                }
                @Override
                public void renderText(TextRenderInfo textRenderInfo) {
                    //去除pdf中文本的空格
                    String strings=textRenderInfo.getText().replace(" ", "").toLowerCase();
                    //当文本长度大于0的时候获得文字矩形范围
                    if (strings.length() > 0) {
                        Rectangle2D.Float baseFloat = textRenderInfo.getBaseline()
                                .getBoundingRectange();
                        Rectangle2D.Float ascentFloat = textRenderInfo.getAscentLine()
                                .getBoundingRectange();
                        //左上角坐标
                        float x = baseFloat.x;
                        float y = baseFloat.y + ((ascentFloat.y - baseFloat.y) );
                        double width = baseFloat.getWidth();
                        double height = baseFloat.getHeight();
                        //把文字的相关信息封装成location对象加入集合，此处为某个页面的所有文字信息
                        locations.add(new Location(strings, x, y, width, height, pageNum));
                    }
                }
                @Override
                public void endTextBlock() {
                }
                @Override
                public void renderImage(ImageRenderInfo imageRenderInfo) {
                }
            });
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        return locations;
    }
    /**
     * 传入的pdf 文件和关键字 返回一个全文中包含所有关键字的信息集合
     * @param pdfPath
     * @param keyWord
     * @return
     */
    public static List<Location> getLastKeyWord(byte[] pdfPath, String keyWord) {
        PdfReader reader = null;
        List<Location> fiList = new ArrayList<Location>();
        char[] a = keyWord.replace(" ","").toLowerCase().toCharArray();
        try {
            reader = new PdfReader(pdfPath);
            //获得pdf的页码
            int num = reader.getNumberOfPages();
            List<Location> locations = null;
            //循环每一页 获得所有的关键字
            for (int i = 0; i< num; i++) {
                try {
                    locations = getKeyWords(reader, i+1);
                } catch (IOException e) {
                    continue;
                }
                if (locations != null && locations.size() > 0) {
                    //根据解析函数筛选包含的关键字（因为pdf中的文本是不规则长度和断句的需要进行筛选）
                    List<Location> list2 = getLocationFromList(locations, a);
                    if (list2 != null) {
                        //把筛选到的内容放入集合中
                        fiList.addAll(list2);
                    }
                }else if(locations == null){
                    continue;
                } else if (i > 0) {
                    //不是第一页的时候继续循环
                    continue;
                } else {
                    //到达第1页结束后关闭reader
                    reader.close();
                    return null;
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            if (reader != null) {
                reader.close();
            }
        }
        return fiList;
    }
    /**
     *  解析关键字的方法 根据输入的页面所有的内容的集合和关键字的char 数组进行匹配
     * @param list
     * @param chars
     * @return
     */
    static List<Location> getLocationFromList(List<Location> list, char[] chars) {
        //定义一个容器集合 收集位置信息对象
        List<Location> list2 = new ArrayList<Location>();
        //获得关键字的长度
        int length = chars.length;
        //循环某个页面中的所有内容
        for (int i = 0; i < list.size(); i++) {
            //关键字出现在某个词组的位置
            int lo = -1;
            //如果大于-1 则代表出现了关键字的第一个字
            if ((lo = list.get(i).getText().indexOf(chars[0])) > -1) {
                //进一步判断，获得该对象的所有文字内容
                String s = list.get(i).getText();
                //计数变量
                int count=0;
                //把该词条后的n个词条加起来 并且n要小于关键字的长度且n加上当前的次数要小于总集合的长度
                for (int j = 1; j < length && (j + i) < list.size(); j++) {
                    s += list.get(i + j).getText();
                    //更新计数次数，以便后面循环跳过计数次数个对象
                    count=j;
                }
                //如果组合的文字包含关键字内容，并且是从当前第一个文字对象起始的
                if (s.contains(new String(chars)) && s.indexOf(new String(chars))<list.get(i).getText().length()) {
                    //更新位置信息，放入集合中
                    Location location1 = list.get(i);
                    Location location = new Location();
                    int textlength = location1.getText().length();
                    location.setText(new String(chars));
                    location.setX(location1.getX() +(float) location1.getWidth() * ((float) lo / textlength));
                    location.setY(location1.getY());
                    location.setPageNum(location1.getPageNum());
                    list2.add(location);
                    //向后推移count个对象
                    i=i+count;
                } else {
                    //循环继续
                    continue;
                }
            } else {
                //循环继续
                continue;
            }
        }
        //返回筛选过的集合
        return list2;
    }
    /**
     * 书签定位查找
     * @param filePath 文件路径
     * @param BookMark 书签名称
     */
    public static Location locationByBookMark(String filePath, String BookMark) throws IOException {
        PdfReader reader = new PdfReader(filePath);
        return locationByBookMark(reader,BookMark);
    }
    /**
     * 书签定位查找
     * @param pdfBytes 文件字符节数组
     * @param BookMark 书签名称
     */
    public static Location locationByBookMark(byte[] pdfBytes, String BookMark) throws IOException {
        PdfReader reader = new PdfReader(pdfBytes);
        return locationByBookMark(reader,BookMark);
    }

    public static Location locationByBookMark(PdfReader reader, String BookMark){
        Location location = null;
        try {
            List<HashMap<String, Object>> bmList = SimpleBookmark.getBookmark(reader);
            for(HashMap<String, Object> hm :bmList){
                if(BookMark.equals(hm.get("Title"))) {
                    location = new Location();
                    Object value = hm.get("Page");
                    String[] a = value.toString().split(" ");
                    location.setPageNum(Integer.parseInt(a[0]));
                    location.setX(Float.parseFloat(a[2]));
                    location.setY(Float.parseFloat(a[3]));
                    location.setText(BookMark);
                }
            }
        }catch (Exception e){
            e.printStackTrace();
        }finally {
            reader.close();
        }
        return location;
    }

    /**
     * 传入的pdf 文件和关键字 返回一个全文中包含所有关键字的信息集合
     * @param pdfPath
     * @param pageNum
     * @return
     */
    public static List<Location> getLastKeyWordXX(byte[] pdfPath, int pageNum) {
        PdfReader reader = null;
        List<Location> fiList = new ArrayList<Location>();
        try {
            reader = new PdfReader(pdfPath);
            //获得pdf的页码
            int num = reader.getNumberOfPages();
            List<Location> locations = null;
            //获得所有的关键字
            locations = getKeyWords(reader, pageNum+1);
            fiList.addAll(locations);
            //到达第1页结束后关闭reader
            reader.close();
        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            if (reader != null) {
                reader.close();
            }
        }
        return fiList;
    }
}
